package com.ms.log.config;

import com.alibaba.fastjson2.JSON;
import com.ms.log.appender.Appender;
import com.ms.log.appender.SimpleConsoleAppender;
import com.ms.log.context.LoggerContext;
import com.ms.log.level.Level;
import com.ms.log.logger.DefaultLogger;
import org.w3c.dom.*;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.net.URL;

/**
 * @author zdh
 */
public class XMLConfigParer implements ConfigParer{

    private final LoggerContext loggerContext;
    private URL url;

    public XMLConfigParer(URL url, LoggerContext loggerContext) {
        this.url = url;
        this.loggerContext = loggerContext;
    }


    @Override
    public void doPare() {
        try{
            // 创建一个新的DocumentBuilderFactory实例
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            // 创建一个新的DocumentBuilder实例
            DocumentBuilder documentBuilder = factory.newDocumentBuilder();
            // 解析XML文件并获取Document对象
            Document document = documentBuilder.parse(url.openStream());
            //解析
            parse(document.getDocumentElement());
        }catch (Exception e){
                e.printStackTrace();
        }
    }


    private void parse(Element document) throws XPathExpressionException, ClassNotFoundException, InstantiationException, IllegalAccessException {
        //do parse...
        //解析 输出器Appender
        paresAppender(document);
        //解析日志记录者 logger
        paresLogger(document);
    }

    private void paresAppender(Element document) throws XPathExpressionException, ClassNotFoundException, InstantiationException, IllegalAccessException {

        // 使用XPath表达式查找所有<appender>元素
        XPath xPath = XPathFactory.newInstance().newXPath();
        String expression = "//appender";
        NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);

        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element element = (Element) node;
                //System.out.println("Appender name: " + element.getAttribute("name"));
//               System.out.println("Appender class: " + element.getAttribute("class"));
                // 这里可以进一步解析每个 appender 的子元素和属性
                String name = element.getAttribute("name");
                Appender appender = (Appender) Class.forName(element.getAttribute("class")).newInstance();
                appender.setAppenderName(name);
                loggerContext.addAppender(name,appender);
            }
        }
    }

    /**
     * 解析 logger 节点
     * @param document
     * @throws XPathExpressionException
     * @throws ClassNotFoundException
     */
    private void paresLogger(Element document) throws XPathExpressionException, ClassNotFoundException {
        // 使用XPath表达式查找所有<logger>元素
        XPath xPath = XPathFactory.newInstance().newXPath();
        String expression = "//logger";
        NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(document, XPathConstants.NODESET);
        for (int i = 0; i < nodeList.getLength(); i++) {
            Node node = nodeList.item(i);
            if (node.getNodeType() == Node.ELEMENT_NODE) {
                Element element = (Element) node;
                String loggerName = element.getAttribute("name");
                String levelStr = element.getAttribute("level");
                Level level = Level.getLevel(levelStr);

                //获取logger 对于的appender
                String ref = parseAppenderRef(node.getChildNodes());
                Appender appender = loggerContext.getAppender(ref);
                if(appender==null){
                    throw new IllegalArgumentException("Appender ref is null");
                }
                DefaultLogger logger = new DefaultLogger(loggerName,appender, level);
                logger.setLevel(level);
                loggerContext.addLogger(loggerName,logger);
            }
        }
    }

    /**
     * 解析 logger 节点中的 appender-ref节点，并返回 ref 属性
     * @param nodeList
     * @return
     */
    private String parseAppenderRef(NodeList nodeList){
        if (nodeList != null) {
            for (int j = 0; j < nodeList.getLength(); j++) {
                Node node = nodeList.item(j);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    Element element = (Element) node;
                    return element.getAttribute("ref");
                }
            }
        }
        return null;
    }
}
